namespace VividKit.ServiceModel
{
    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;

    public class TraceCommandDispatcher : ICommandDispatcher
    {
        private readonly ICommandDispatcher commandDispatcher;
        private readonly TraceSource log;

        public TraceCommandDispatcher(ICommandDispatcher commandDispatcher)
        {
            this.commandDispatcher = commandDispatcher;
            this.log = new TraceSource(this.commandDispatcher.GetType().Name, SourceLevels.Information);
        }

        public async Task ExecuteAsync<TCommand>(TCommand command) where TCommand : class, ICommand
        {
            var stopwatch = new Stopwatch();
            try
            {
                this.log.TraceEvent(TraceEventType.Information, 0, "Executing {0}", command.GetType().Name);
                this.log.TraceObject(TraceEventType.Verbose, 0, command);
                stopwatch.Start();
                await this.commandDispatcher.ExecuteAsync(command);
            }
            catch (Exception x)
            {
                this.log.TraceData(TraceEventType.Warning, 0, x);
                throw;
            }
            finally
            {
                stopwatch.Stop();
                this.log.TraceEvent(TraceEventType.Information, 0, "Executed {0} ({1} ms)",
                    command.GetType().Name, stopwatch.ElapsedMilliseconds);
            }
        }
    }
}